#include "virtualcar.h"
#include "ui_virtualcar.h"

#include"QJsonDocument"
#include"QJsonObject"
#include"QJsonArray"
#include"QJsonValue"
#include<QPainter>
#include <QTimer>
//虚拟小车
//定时移动
VirtualCar::VirtualCar(const int &id,QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::VirtualCar),
      id(id)
{
    ui->setupUi(this);

    socket.connectToHost("127.0.0.1",10086);    //信号与槽的绑定

    connect(&socket,&QTcpSocket::stateChanged,
            this,&VirtualCar::slot_stateChanged);

    connect(&socket,&QTcpSocket::readyRead,
            this,&VirtualCar::slot_readyRead);
    //以求连接一辆显示一辆
   // srand(time(nullptr));
    road_id=rand()%14;
    duration=(rand()%100)/100.0f;

    timer=new QTimer(this);
    timer->setInterval(1000);
    connect(timer,&QTimer::timeout,this,&VirtualCar::slot_move);
    timer->start();//启动定时器
    init();
}

VirtualCar::~VirtualCar()
{
    delete ui;
}

void VirtualCar::paintEvent(QPaintEvent *e)
{
    QPainter painter;
    QImage img(":/pic/lyt.jpg");
    painter.begin(this);
    painter.drawImage(this->rect(),img,img.rect());
    painter.end();
}

void VirtualCar::slot_stateChanged(QAbstractSocket::SocketState state)
{
    if(state == QAbstractSocket::UnconnectedState) {
          //连接失败 重新链接
          socket.connectToHost("127.0.0.1",10086);
          this->setWindowTitle("小车 "+QString::number(id)+" - 链接失败");
      } else if (state == QAbstractSocket::ConnectedState) {
          //链接成功 暂时什么都不干
          this->setWindowTitle("小车" +QString::number(id)+" - 链接成功");
        QTimer::singleShot(500,[this](){
            sendId();
            sendState();//仅作测试
        });
        sendId();
      }else if (state == QAbstractSocket::ConnectingState) {
          this->setWindowTitle("小车  "+QString::number(id)+" - 正在链接");
    }
}

//每到一个路口随机跑
void VirtualCar::slot_move()
{
    duration += 0.05f;
    if (duration > 1.0f)
    {
        timer->stop();//一旦走到路口就停下来
        SendGetCrossState();//等待信息返回
    }
    sendState();
}

//小车通过
void VirtualCar::slot_readyRead()
{
    QTcpSocket *socket = dynamic_cast<QTcpSocket *>(sender());
    QByteArray data = socket->readAll();
    QList<QJsonObject> list_obj = splitJsonObjects(data);
    for(auto obj : list_obj){
        if(obj.contains("code")) {
            // 所有的信息都会包含该字段
            int code = obj.value("code").toInt();
            switch (code) {
            //熄火指令
            case 10003:
            {
                int carId=obj.value("id").toInt();
                if(this->id==carId){
                    qDebug()<<this->id<<"熄火了";
                    timer->stop();
                }
            }
                break;
            case 10004:{
                           bool state = obj.value("state").toBool();
                           if(state){
                               //可以走
                               int i;
                               int node = list_line[road_id].end;
                               for (i = 0; i < 4; i++)
                               {
                                   int line = list_node[node].in_roads_id[i];
                                   if (line >= 0 && list_line[line].id == road_id)
                                   {
                                       break;
                                   }
                               }
                               if (i >= 4)
                               {
                                   duration = 1.0f;
                               }
                               else
                               {
                                   i = (i + 4) % 4;
                                   // 直行 +2，左转 +1，右转 -1，掉头什么都不做
                                   // 让小车随机转向
                                   // 考虑转向有没有路
                                   int road;
                                   if (i == 0) // 直行
                                   {
                                       road = list_node[node].out_roads_id[(i + 2) % 4];
                                   }
                                   else if (i == 1) // 左转
                                   {
                                       road = list_node[node].out_roads_id[(i + 1) % 4];
                                   }
                                   else if (i == 2) // 右转
                                   {
                                       road = list_node[node].out_roads_id[(i - 1) % 4];
                                   }
                                   else // 掉头
                                   {
                                       road = list_node[node].out_roads_id[i];
                                   }
                                   if (road >= 0)
                                   {
                                       road_id = road;
                                   }
                                   else // 如果road=-1，说明直线行驶没有路，进行掉头
                                   {
                                       road_id = list_node[node].out_roads_id[i];
                                   }
                                   duration = 0.0f;
                               }
                               timer->start();
                           }else{
                               //不能走
                               QTimer::singleShot(500,[this]()
                               {
                                   SendGetCrossState();
                               }
                               );
                           }
            }
                break;
            case 10005: // 添加恢复运动的指令
                        {
                            int carId = obj.value("id").toInt();
                            if (this->id == carId) {
                                qDebug() << this->id << "恢复运动";
                                timer->start();
                            }
                        }
                            break;
            }
        }
    }
}
void VirtualCar::init()
{
    int node_id=0;
    Node node0(node_id++);
    Node node1(node_id++);
    Node node2(node_id++);
    Node node3(node_id++);
    Node node4(node_id++);
    Node node5(node_id++);

    int line_id=0;
    Line line0(line_id++);
    Line line1(line_id++);
    Line line2(line_id++);
    Line line3(line_id++);
    Line line4(line_id++);
    Line line5(line_id++);
    Line line6(line_id++);
    Line line7(line_id++);
    Line line8(line_id++);
    Line line9(line_id++);
    Line line10(line_id++);
    Line line11(line_id++);
    Line line12(line_id++);
    Line line13(line_id++);

    line0.end=0;line0.start=1;
    line1.end=1;line1.start=0;
    line2.end=2;line2.start=0;
    line3.end=0;line3.start=2;
    line4.end=3;line4.start=1;
    line5.end=1;line5.start=3;
    line6.end=2;line6.start=3;
    line7.end=3;line7.start=2;
    line8.end=4;line8.start=2;
    line9.end=2;line9.start=4;
    line10.end=5;line10.start=3;
    line11.end=3;line11.start=5;
    line12.end=4;line12.start=5;
    line13.end=5;line13.start=4;

    //0号入口
    node0.in_roads_id.append(-1);node0.in_roads_id.append(0);
    node0.in_roads_id.append(3);node0.in_roads_id.append(-1);
    node0.out_roads_id.append(-1);node0.out_roads_id.append(1);
    node0.out_roads_id.append(2);node0.out_roads_id.append(-1);
    //1号入口
    node1.in_roads_id.append(-1);node1.in_roads_id.append(-1);
    node1.in_roads_id.append(5);node1.in_roads_id.append(1);
    node1.out_roads_id.append(-1);node1.out_roads_id.append(-1);
    node1.out_roads_id.append(4);node1.out_roads_id.append(0);
    //2号入口
    node2.in_roads_id.append(2);node2.in_roads_id.append(6);
    node2.in_roads_id.append(9);node2.in_roads_id.append(-1);
    node2.out_roads_id.append(3);node2.out_roads_id.append(7);
    node2.out_roads_id.append(8);node2.out_roads_id.append(-1);
    //3号入口
    node3.in_roads_id.append(4);node3.in_roads_id.append(-1);
    node3.in_roads_id.append(11);node3.in_roads_id.append(7);
    node3.out_roads_id.append(5);node3.out_roads_id.append(-1);
    node3.out_roads_id.append(10);node3.out_roads_id.append(6);
    //4号入口
    node4.in_roads_id.append(8);node4.in_roads_id.append(12);
    node4.in_roads_id.append(-1);node4.in_roads_id.append(-1);
    node4.out_roads_id.append(9);node4.out_roads_id.append(13);
    node4.out_roads_id.append(-1);node4.out_roads_id.append(-1);
    //5号入口
    node5.in_roads_id.append(10);node5.in_roads_id.append(-1);
    node5.in_roads_id.append(-1);node5.in_roads_id.append(13);
    node5.out_roads_id.append(11);node5.out_roads_id.append(-1);
    node5.out_roads_id.append(-1);node5.out_roads_id.append(12);

    list_line.append(line0);
    list_line.append(line1);
    list_line.append(line2);
    list_line.append(line3);
    list_line.append(line4);
    list_line.append(line5);
    list_line.append(line6);
    list_line.append(line7);
    list_line.append(line8);
    list_line.append(line9);
    list_line.append(line10);
    list_line.append(line11);
    list_line.append(line12);
    list_line.append(line13);

    list_node.append(node0);
    list_node.append(node1);
    list_node.append(node2);
    list_node.append(node3);
    list_node.append(node4);
    list_node.append(node5);
}

void VirtualCar::sendId()
{
    //发送身份ID
    //code表示身份信息，type表示身份，id表示id
    QJsonObject obj;
    obj.insert("code",20001);//发送身份信息
    obj.insert("type","car");
    obj.insert("id",id);
    socket.write(QJsonDocument(obj).toJson());//消息会发送给服务器
}

void VirtualCar::sendState()
{
    //已连接状态才需要发送
    if(socket.state()==QAbstractSocket::ConnectedState){
        QJsonObject obj;
        obj.insert("code",30001);//发送小车状态信息
        obj.insert("id",id);
        obj.insert("road_id",road_id);
        obj.insert("duration",duration);//float->doubl
        socket.write(QJsonDocument(obj).toJson());//消息会发送给服务器
    }
    ui->label->setText("road_id:"+QString::number(road_id));
    ui->label_2->setText("duration"+QString::number(duration*100.0f)+"%");
}

void VirtualCar::SendGetCrossState()
{
    //已连接状态才发送信息
    if(socket.state()==QAbstractSocket::ConnectedState)
    {
        QJsonObject obj;
        obj.insert("code",30002);
        obj.insert("road_id",road_id);
        socket.write(QJsonDocument(obj).toJson());//消息发送到服务器
    }
}

QList<QJsonObject> VirtualCar::splitJsonObjects(const QByteArray &data)
{
    QList<QJsonObject> list_obj;
        int braceCount = 0;
        int startIndex = 0;
        for (int i = 0; i < data.size(); ++i) {
            if (data[i] == '{') {
                if (braceCount == 0) {
                    startIndex = i;
                }
                braceCount++;
            } else if (data[i] == '}') {
                braceCount--;
                if (braceCount == 0) {
                    QByteArray json = data.mid(startIndex, i - startIndex + 1);
                    QJsonDocument doc = QJsonDocument::fromJson(json);
                    QJsonObject obj = doc.object();
                    list_obj.append(obj);
                }
            }
        }
        return list_obj;
}

